package pers.mine.utils;

import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncoderException;
import it.sauronsoftware.jave.InputFormatException;
import it.sauronsoftware.jave.MultimediaInfo;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.springframework.web.multipart.MultipartFile;

/**
 * 一个工具类,用于封装一些有用的小方法,一般都是静态的 screw -->螺丝
 * 
 * @author Mine
 * 
 */
public class MineScrewUtils {
	/**
	 * 获取指定字符串的MD5算法值
	 * 
	 * @param msg
	 *            指定字符串
	 * @return 大写后的16进制字符串长度32
	 */
	public static String getMD5(String msg) {
		String md5Msg = "";
		try {
			// 1.创建一个信息摘要算法对象,初始化为MD5
			MessageDigest md = MessageDigest.getInstance("MD5");
			// 2.将msg转换为byte[]
			byte[] temp = msg.getBytes();
			// 3.使用md5算法计算,获得执行算法后[哈希值结果]的 byte 数组。
			byte[] byteResult = md.digest(temp);
			// 4.将byte数组每一个字节转换为16进制字符串并拼接 -->最后转换为大写
			md5Msg = bytesToHex(byteResult).toUpperCase();
		} catch (NoSuchAlgorithmException e) {
			// 如果指定算法的 MessageDigestSpi 实现不能从指定提供者获得。
			e.printStackTrace();
			System.err.println("MD创建发生错误...");
		}
		return md5Msg;
	}

	/**
	 * 将byte数组转换为16进制并拼接成字符串返回
	 * 
	 * @param bytes
	 *            byte数组
	 * @return 16进制字符串
	 */
	public static String bytesToHex(byte[] bytes) {
		StringBuffer strBf = new StringBuffer();
		if (bytes == null || bytes.length < 1) {// 非法数据
			return null;
		}
		int length = bytes.length;
		int intTemp = 0;
		String strTemp = null;
		for (int i = 0; i < length; i++) {
			// 1、先转换为十进制
			intTemp = bytes[i] & 0xFF;// 之所以&0xFF是因为int是32位,byte8位,高位要清0
			// 2.十进制转十六进制
			strTemp = Integer.toHexString(intTemp);
			// 3.位数不足则以0补位
			if (strTemp.length() < 2) {
				strBf.append(0);
			}
			// 4、追加
			strBf.append(strTemp);
		}
		return strBf.toString();
	}

	/**
	 * 获取web项目基地址
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	public static String getBasepath(HttpServletRequest request,
			HttpServletResponse response) {
		String path = request.getContextPath();
		String basePath = request.getScheme() + "://" + request.getServerName()
				+ ":" + request.getServerPort() + path + "/";
		return basePath;
	}

	/**
	 * 上传控制方法
	 * 
	 * @return boolean false 表示处理失败
	 * */
	public static boolean doUpload(String onePath, String realsavePath,
			Map<String, String> map, HttpServletRequest request) {
		boolean flag = true;

		File dir = new File(realsavePath);
		// 确保目录存在
		if (!dir.exists() && !dir.isDirectory()) {
			dir.mkdirs();// 可创建多级目录
		}
		System.out.println("绝对路径:" + dir.getAbsolutePath());
		try {
			/*
			 * 使用Apache上传组件 处理文件上传步骤:
			 * 1.创建DiskFileItemFactory工厂,可设置缓存区大小setSizeThreshold(1024*10);
			 * 2.创建一个文件上传解析器 ServletFileUpload 构造方法需要 "1" - "工厂 "作为参数
			 * setHeaderEncoding("Utf-8") 解决乱码 3.判断提交数据是否为上传表单数据 //否则按照request
			 * 获取 (boolean) ServletFileUpload.isMultipartContent(request)
			 * 设置上传单个文件大小最大值 upload.setFileSizeMax(1024*1024) 设置上传文件总量的最大值
			 * ps:支持同时上传多个文件 upload.setSizeMax(1024*1024*10)
			 * 4.使用ServletFileUpload解析器解析上传数据,返回结果是一个List<FileItem>集合
			 * 每个FileItem对应一个表单提交项 List<FileItem>
			 * fs=upload.parseRequest(request);
			 */
			DiskFileItemFactory factory = new DiskFileItemFactory();
			factory.setSizeThreshold(1024 * 128);// 默认10kb

			ServletFileUpload upload = new ServletFileUpload();
			upload.setFileItemFactory(factory);
			upload.setHeaderEncoding("utf-8");
			if (!ServletFileUpload.isMultipartContent(request)) {
				System.out.println("没有表单。。。");
				return false;
			}
			upload.setFileSizeMax(1024 * 1024);
			upload.setSizeMax(1024 * 1024 * 8);

			List<FileItem> fs = upload.parseRequest(request);
			for (FileItem fi : fs) {
				String valName = fi.getFieldName();
				if (fi.isFormField()) {// 如果上传 项为普通数据
					valName = fi.getFieldName();
					// 中文解决乱码
					String value = fi.getString("UTF-8");
					System.out.println(valName + ":" + value);
					// 放入vomap
					map.put(valName, value);
				} else {
					// 上传文件类型
					valName = fi.getFieldName();// 获取属性名

					String fileName = fi.getName(); // 文件全路径

					String filenewNamePath = null;// 解决唯一性问题 UUID
					if (fileName == null || "".equals(fileName.trim())) {
						flag = false;// 文件名错误
						continue;
					}
					// 出于文件名格式的不同 取得处理后的文件名
					fileName = fileName
							.substring(fileName.lastIndexOf("\\") + 1);
					System.out.println(fileName);
					// 获得文件后缀名
					String fileExtName = fileName.substring(fileName
							.lastIndexOf(".") + 1);
					System.out.println(fileExtName);
					if (fileExtName == null
							|| (!"jpg".equalsIgnoreCase(fileExtName))) {
						// 只处理.jpg图片
						flag = false;
						continue;
					}

					// 拼接全路径
					filenewNamePath = UUID.randomUUID().toString() + "."
							+ fileExtName;

					InputStream in = fi.getInputStream();
					FileOutputStream fos = new FileOutputStream(realsavePath
							+ "\\" + filenewNamePath);
					// 创建一个缓存区
					byte buffer[] = new byte[1024];
					int len = 0;
					while ((len = in.read(buffer)) > 0) {
						fos.write(buffer, 0, len);
					}
					// 关闭流
					in.close();
					fos.close();
					// 删除临时文件
					fi.delete();
					// 新名字以及相对路径放入vomap 斜杠和反斜杠?
					map.put(valName, onePath + "/" + filenewNamePath);
				}

			}
		} catch (Exception e) {
			System.err.println("发生异常...");
			flag = false;
		}
		return flag;
	}

	/**
	 * 基于SpringMVC的上传处理
	 * @param fileParentPath 文件存放目录
	 * @param prefix 新文件名前缀
	 * @param allowedSuffixs 被允许的文件类型
	 * @param file
	 * @param request
	 * @return 新文件名,失败为null]
	 */
	public static String upLoadFileForStringMVC(String fileParentPath,
			String prefix,String[] allowedSuffixs, MultipartFile file) throws Exception{
		// 获取真实文件后缀
		String[] strArr = file.getOriginalFilename().split("\\.");
		// 如果资源不存在也会返回
		if (strArr == null || strArr.length < 2) {
			throw new Exception("接收文件发生错误!");
		}
		String suffix = strArr[strArr.length - 1];
		String newfileName = prefix + "_" + MineCommonUtils.getUUID_NoHyphen() + "." + suffix;
		// 判断后缀
		if (!MineStringUtils.strIsInStrArrIgnoreCase(suffix, allowedSuffixs)) {
			throw new Exception("错误的文件类型!");
		}
		File one = new File(new File(fileParentPath), newfileName);
		// System.out.println(one.getAbsolutePath());
		try {
			FileUtils.copyInputStreamToFile(file.getInputStream(), one);
			return newfileName;
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		throw new Exception("文件写入失败!");
	}
	
	/**
	 * 删除一个文件
	 * @param path 父目录 (非空)
	 * @param fileName 文件名(非空)
	 * @return 删除结果
	 */
	public static boolean delFile(String path,String fileName){
		boolean flag = false;
		if(MineStringUtils.IsNullOrWhiteSpace(path)||MineStringUtils.IsNullOrWhiteSpace(fileName)){
			return false;
		}
		try {
			File directory = new  File(path.trim());
			if(directory.isDirectory()){
				File f = new File(directory,fileName.trim());
				if(f.exists()){
					if(f.delete()){
						flag = true;
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return flag;
	}
	
	/**
	 * 获取指定视频文件的时间长度
	 * @param videoFile
	 * @return
	 * @throws InputFormatException
	 * @throws EncoderException
	 */
	public static double getVideoDuration(File videoFile) throws InputFormatException, EncoderException{
		 Encoder encoder = new Encoder();
		 MultimediaInfo m = encoder.getInfo(videoFile);
		 return m.getDuration();
	}
	/** 获取指定视频文件的时间长度*/
	public static double getVideoDuration(String videoFilePath) throws Exception{
		File file = new File(videoFilePath);
		return getVideoDuration(file);
	}
	/** 获取指定视频文件的时间长度*/
	public static double getVideoDuration(String fileParentPath,String videoFireName) throws Exception{
		File file = new File(fileParentPath,videoFireName);
		return getVideoDuration(file);
	}
	
	 public static  String readJSONStringByRequest(HttpServletRequest request){
	        StringBuffer json = new StringBuffer();
	        String line = null;
	        BufferedReader reader=null;
	        try {
	            reader = request.getReader();
	            while((line = reader.readLine()) != null) {
	                json.append(line);
	            }
	        }
	        catch(Exception e) {
	        	if(reader!=null){try {
					reader.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}}
	        	e.printStackTrace();
	        }
	        return json.toString();
	    }
}
